package com.yilin.platform.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.gson.reflect.TypeToken;
import com.yilin.platform.base_core.application.UserUtil;
import com.yilin.platform.base_core.application.ReturnData;
import com.yilin.platform.base_core.commons.encrypt.EncryptUtils;
import com.yilin.platform.base_core.commons.exception.BusinessException;
import com.yilin.platform.base_core.commons.utils.HttpService;
import com.yilin.platform.base_core.commons.utils.JsonUtil;
import com.yilin.platform.base_core.commons.utils.MapUtil;
import com.yilin.platform.base_core.commons.utils.StringUtil;
import com.yilin.platform.entity.user.deserialize.Account;
import com.yilin.platform.entity.user.AccountConfigure;
import com.yilin.platform.entity.user.deserialize.UserType;
import com.yilin.platform.mapper.user.AccountConfigureMapper;
import com.yilin.platform.service.IUserService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Transactional
public class UserService implements IUserService {

    @Value("${yilin-base-url}")
    private String yilinBaseUrl;//易林平台基础服务地址
    @Value("${yilin-web-url}")
    private String yilinWebUrl;//易林平台基础服务地址
    @Resource
    AccountConfigureMapper accountConfigureMapper;

    //连续请求失败次数
    private int netErrCount = 0;

    @Override
    public Account loginToYilin(String username, String customerKey) {
        Map<String, Object> param = new HashMap<>();
        Map<String, String> header = new HashMap<>();
        param.put("username", username);
        param.put("customerKey", customerKey);
        String body = JsonUtil.objectToJson(param);
        String apiToken = null;
        String encrypt = EncryptUtils.aesEncrypt(body, apiToken);
        Map<String, Object> map = new HashMap<>();
        map.put("body", encrypt);
        String result = HttpService.httpPostWithJson(yilinBaseUrl + "/user/login/keyLogin", JsonUtil.objectToJson(map), header);
        ReturnData<Account> returnData = JsonUtil.jsonToObject(result, new TypeToken<ReturnData<Account>>() {
        });
        if (returnData == null) throw new BusinessException("请求返回为空");
        if (!returnData.isSuccess()) throw new BusinessException(returnData.getMsg());//887登录授权已过期
        if (returnData.getToken() != null) apiToken = returnData.getToken();
        String resultJson = EncryptUtils.aesDecrypt(returnData.getEncData(), apiToken);
        Account account = JsonUtil.jsonToObject(resultJson, new TypeToken<Account>() {
        });
        if (account == null) throw new BusinessException("初始化失败，鉴权用户为空");
        if(account.getUserType()!= UserType.platformUser)throw new BusinessException("非网货平台用户禁止登录");
        UserUtil.saveLoginUser(account.getToken(), account);
        AccountConfigure accountConfigure = getAccountConfigure();
        AccountConfigure accountConfigureNew = new AccountConfigure();
        accountConfigureNew.setSafeKey(customerKey);
        accountConfigureNew.setUsername(username);
        accountConfigureNew.setToken(account.getToken());
        accountConfigureNew.setPlatId(account.getOrganizeId());
        if (accountConfigure == null) {
            accountConfigureMapper.insert(accountConfigureNew);
        } else {//
            accountConfigureNew.setId(accountConfigure.getId());
            accountConfigureMapper.updateById(accountConfigureNew);
        }
        return account;
    }

    @Override
    public Account getYilinLoginUser(String token) {
        Map<String, String> header = MapUtil.generate(map -> map.put("token", token));
        return request("/user/account/getLoginUserInfo", token, new HashMap<>(), new TypeToken<Account>() {
        });
    }

    @Override
    public AccountConfigure getAccountConfigure() {
        QueryWrapper<AccountConfigure> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByAsc("username");
        List<AccountConfigure> list = accountConfigureMapper.selectList(queryWrapper);
        if (list == null || list.size() == 0) return null;
        if (list.size() > 1) throw new BusinessException("平台数据错误，生成多个账户");
        return list.get(0);
    }

    @Override
    public <T> T request(String path, Map<String, Object> param, TypeToken<T> typeToken) {
        return request(path, null, param, typeToken);
    }

    @Override
    public <T> T request(String path, String apiToken, Map<String, Object> param, TypeToken<T> typeToken) {
            AccountConfigure accountConfigure = getAccountConfigure();
            Map<String, String> header = new HashMap<>();
            String body = JsonUtil.objectToJson(param);
            if (apiToken != null) header.put("token", apiToken);
            String encrypt = EncryptUtils.aesEncrypt(body, apiToken);
            Map<String, Object> map = new HashMap<>();
            map.put("body", encrypt);
            String result = HttpService.httpPostWithJson(yilinBaseUrl + path, JsonUtil.objectToJson(map), header);
            if (StringUtil.isEmpty(result)) throw new BusinessException("请求返回为空");
            ReturnData<T> returnData = null;
            try {
                returnData = JsonUtil.jsonToObject(result, new TypeToken<ReturnData<T>>() {});
            } catch (Exception e) {
                return  (T)result;
            }
            if (returnData == null) throw new BusinessException("请求返回为空");
            if (!returnData.isSuccess()) {
                if (returnData.getCode() == 401) {//登录失效
                    if (accountConfigure == null) throw new BusinessException("未获取到授权信息,请先授权");//887登录授权已过期
                    this.netErrCount++;
                    if (this.netErrCount > 5) throw new BusinessException("连续(自动)请求失败次数过多，请稍后再试！");
                    loginToYilin(accountConfigure.getUsername(), accountConfigure.getSafeKey());
                    throw new BusinessException("登录失效，已自动重新登录，请稍后重试");//887登录授权已过期
                }
                throw new BusinessException(returnData.getMsg());//887登录授权已过期
            }
            this.netErrCount = 0;
            if (returnData.getToken() != null) apiToken = returnData.getToken();
            String resultJson = EncryptUtils.aesDecrypt(returnData.getEncData(), apiToken);
            return JsonUtil.jsonToObject(resultJson, typeToken);
    }


    @Override
    public String getYilinWebUrl() {
        return yilinWebUrl;
    }

    @Override
    public String getYilinBaseUrl() {
        return yilinBaseUrl;
    }
}
